class SceneControl {
    constructor() {
        if (SceneControl.instance) {
            return SceneControl.instance;
        }
        SceneControl.instance = this;
    }
    tokml(geojson, options) {
        options = options || {
            documentName: undefined,
            documentDescription: undefined,
            name: 'name',
            description: 'description',
            simplestyle: false,
            timestamp: 'timestamp'
        };
        return '<?xml version="1.0" encoding="UTF-8"?>' +
            tag('kml',
                tag('Document',
                    documentName(options) +
                    documentDescription(options) +
                    root(geojson, options)
                ), [
                    ['xmlns', 'http://www.opengis.net/kml/2.2']
                ]);
    }
    downloadShp(geojson) {
        try {
            shpwrite.download(geojson);
        } finally {
            console.log('err');
        }
    }

}
// geojson数据处理 转变为 kml格式
var geometry = {
    Point: function(_) {
        return tag('Point', tag('coordinates', _.coordinates.join(',')));
    },
    LineString: function(_) {
        return tag('LineString', tag('coordinates', linearring(_.coordinates)));
    },
    Polygon: function(_) {
        if (!_.coordinates.length) return '';
        var outer = _.coordinates[0],
            inner = _.coordinates.slice(1),
            outerRing = tag('outerBoundaryIs',
                tag('LinearRing', tag('coordinates', linearring(outer)))),
            innerRings = inner.map(function(i) {
                return tag('innerBoundaryIs',
                    tag('LinearRing', tag('coordinates', linearring(i))));
            }).join('');
        return tag('Polygon', outerRing + innerRings);
    },
    MultiPoint: function(_) {
        if (!_.coordinates.length) return '';
        return tag('MultiGeometry', _.coordinates.map(function(c) {
            return geometry.Point({ coordinates: c });
        }).join(''));
    },
    MultiPolygon: function(_) {
        if (!_.coordinates.length) return '';
        return tag('MultiGeometry', _.coordinates.map(function(c) {
            return geometry.Polygon({ coordinates: c });
        }).join(''));
    },
    MultiLineString: function(_) {
        if (!_.coordinates.length) return '';
        return tag('MultiGeometry', _.coordinates.map(function(c) {
            return geometry.LineString({ coordinates: c });
        }).join(''));
    },
    GeometryCollection: function(_) {
        return tag('MultiGeometry',
            _.geometries.map(geometry.any).join(''));
    },
    valid: function(_) {
        return _ && _.type && (_.coordinates ||
            _.type === 'GeometryCollection' && _.geometries.every(geometry.valid));
    },
    any: function(_) {
        if (geometry[_.type]) {
            return geometry[_.type](_);
        } else {
            return '';
        }
    }
};

function tag(el, contents, attributes) {
    return '<' + el + attr(attributes) + '>' + contents + '</' + el + '>';
}

function documentName(options) {
    return (options.documentName !== undefined) ? tag('name', options.documentName) : '';
}

function documentDescription(options) {
    return (options.documentDescription !== undefined) ? tag('description', options.documentDescription) : '';
}

function root(_, options) {
    if (!_.type) return '';
    switch (_.type) {
        case 'FeatureCollection':
            if (!_.features) return '';
            return _.features.map(feature(options)).join('');
        case 'Feature':
            return feature(options)(_);
        default:
            return feature(options)({
                type: 'Feature',
                geometry: _,
                properties: {}
            });
    }
}

function feature(options) {
    return function(_) {
        var styleDefinition = '',
            styleReference = '';
        if (options.simplestyle && hasStyle(_.properties)) {
            styleDefinition = iconstyle(_.properties);
            styleReference = tag('styleUrl', '#' + iconHash(_.properties));
        }
        if (!_.properties || !geometry.valid(_.geometry)) return '';
        var geometryString = geometry.any(_.geometry);
        if (!geometryString) return '';
        return styleDefinition + tag('Placemark',
            name(_.properties, options) +
            description(_.properties, options) +
            extendeddata(_.properties) +
            timestamp(_.properties, options) +
            geometryString +
            styleReference);
    };
}

function attr(_) {
    return (_ && _.length) ? (' ' + _.map(function(a) {
        return a[0] + '="' + a[1] + '"';
    }).join(' ')) : '';
}

function iconHash(_) {
    return (_['marker-symbol'] || '') +
        (_['marker-color'] || '').replace('#', '') +
        (_['marker-size'] || '');
}

function linearring(_) {
    return _.map(function(cds) { return cds.join(','); }).join(' ');
}

function name(_, options) {
    return _[options.name] ? tag('name', encode(_[options.name])) : '';
}

function encode(_) {
    return (_ === null ? '' : _.toString()).replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;');
}

function description(_, options) {
    return _[options.description] ? tag('description', encode(_[options.description])) : '';
}

function timestamp(_, options) {
    return _[options.timestamp] ? tag('TimeStamp', tag('when', encode(_[options.timestamp]))) : '';
}

function extendeddata(_) {
    return tag('ExtendedData', pairs(_).map(data).join(''));
}

function pairs(_) {
    var o = [];
    for (var i in _) o.push([i, _[i]]);
    return o;
}

function data(_) {
    return tag('Data', tag('value', encode(_[1])), [
        ['name', encode(_[0])]
    ]);
}


SceneControl.getInstance = function() {
    if (SceneControl.instance) {
        return SceneControl.instance;
    }
    return (SceneControl.instance = new SceneControl());
};

SceneControl.removeInstance = function() {
    SceneControl.instance = undefined;
    Plotting.removeInstance();
    Measure.removeInstance();
};

export default SceneControl;